package com.health_and_exercise.healthandexercisev1.app;

import android.app.IntentService;
import android.app.Service;
import android.content.Context;
import android.content.Intent;
import android.hardware.Sensor;
import android.hardware.SensorEvent;
import android.hardware.SensorEventListener;
import android.hardware.SensorManager;
import android.os.Bundle;
import android.os.CountDownTimer;
import android.os.IBinder;
import android.os.Vibrator;
import android.support.v4.content.LocalBroadcastManager;
import android.util.Log;
import android.widget.Toast;

/**
 * Created by jinzhang on 5/29/14.
 */
public class BackgroundService extends Service implements SensorEventListener {
    private long targetTimeMilli;
    private CountDownTimer countDownTimer;
    private int numOfSteps;
    private int numOfJumps;
    private int targetSteps;
    private float lightReading;
    private float proximityReading;
    private boolean jumpStarted = false;
    private SensorManager sensorManager;

    private void registerSensor(Sensor sensor, int sensorDelayUi) {
        if (sensor != null) {
            boolean sensorExists = sensorManager.registerListener(this, sensor, sensorDelayUi);
            if (!sensorExists) {
                Toast.makeText(this, String.format("Sensor %s not available!", sensor.getName()),
                        Toast.LENGTH_LONG).show();
            }
        } else {
            Toast.makeText(this, String.format("Sensor is not available!"),
                    Toast.LENGTH_LONG).show();
        }
    }

    @Override
    public IBinder onBind(Intent intent) {
        return null;
    }

    @Override
    public void onCreate() {
        sensorManager = (SensorManager) getSystemService(Context.SENSOR_SERVICE);
        Sensor countStepSensor = sensorManager.getDefaultSensor(Sensor.TYPE_STEP_COUNTER);
        Sensor lightSensor = sensorManager.getDefaultSensor(Sensor.TYPE_LIGHT);
        Sensor proximitySensor = sensorManager.getDefaultSensor(Sensor.TYPE_PROXIMITY);
        Sensor stepDetectionSensor = sensorManager.getDefaultSensor(Sensor.TYPE_STEP_DETECTOR);
        Sensor accelerometerSensor = sensorManager.getDefaultSensor(Sensor.TYPE_ACCELEROMETER);

        registerSensor(countStepSensor, SensorManager.SENSOR_DELAY_NORMAL);
        registerSensor(lightSensor, SensorManager.SENSOR_DELAY_NORMAL);
        registerSensor(proximitySensor, SensorManager.SENSOR_DELAY_NORMAL);
        registerSensor(stepDetectionSensor, SensorManager.SENSOR_DELAY_NORMAL);
        registerSensor(accelerometerSensor, SensorManager.SENSOR_DELAY_FASTEST);

        super.onCreate();
    }

    @Override
    public void onDestroy() {

        countDownTimer.cancel();
        sensorManager.unregisterListener(this);
        super.onDestroy();
    }

    @Override
    public int onStartCommand(Intent intent, int flags, int startId) {
        Bundle bundle = intent.getExtras();
        targetTimeMilli = bundle.getLong("TARGET_TIME");
        targetSteps = bundle.getInt("TARGET_STEP");
        Log.d("service", "targetSteps = " + String.valueOf(targetSteps));

        countDownTimer = new CountDownTimer(targetTimeMilli - System.currentTimeMillis(),
                1000) {

            public void onTick(long millisUntilFinished) {
                Intent localIntent = new Intent();
                localIntent.setAction("BROADCAST_ACTION");

                Bundle finishBundle = new Bundle();
                if (numOfSteps > 0 && numOfSteps >= targetSteps) {

                    finishBundle.putBoolean("LGTM", true);
                    finishBundle.putInt("NUM_OF_STEPS", numOfSteps);
                    finishBundle.putFloat("LIGHT_READING", lightReading);
                    finishBundle.putFloat("PROXIMITY_READING", proximityReading);
                    finishBundle.putInt("NUM_OF_JUMPS", numOfJumps);
                    localIntent.putExtras(finishBundle);
                    sendBroadcast(localIntent);
                    this.cancel();
                } else {

                    finishBundle.putLong("REMAINING_SECONDS", millisUntilFinished / 1000);
                    finishBundle.putInt("NUM_OF_STEPS", numOfSteps);
                    finishBundle.putFloat("LIGHT_READING", lightReading);
                    finishBundle.putFloat("PROXIMITY_READING", proximityReading);
                    finishBundle.putInt("NUM_OF_JUMPS", numOfJumps);
                    finishBundle.putBoolean("LGTM", false);
                    localIntent.putExtras(finishBundle);
                    sendBroadcast(localIntent);
                }


                //Log.d("service", "targetSteps = " + String.valueOf(targetSteps) + "; numOfSteps = " + String.valueOf(numOfSteps));
                //Log.d("tick tick tick ", "lightReading = " + String.valueOf(lightReading) +
                  //  "; proximityReading = " + String.valueOf(proximityReading) +
                    //"; remaining_seconds = " + String.valueOf(millisUntilFinished / 1000));
                // Broadcasts the Intent to receivers in this app.


            }

            public void onFinish() {
                Intent localIntent = new Intent();
                localIntent.setAction("BROADCAST_ACTION");

                Bundle finishBundle = new Bundle();
                finishBundle.putLong("REMAINING_SECONDS", 0);
                finishBundle.putInt("NUM_OF_STEPS", numOfSteps);
                finishBundle.putFloat("LIGHT_READING", lightReading);
                finishBundle.putFloat("PROXIMITY_READING", proximityReading);
                finishBundle.putInt("NUM_OF_JUMPS", numOfJumps);
                finishBundle.putBoolean("LGTM", true);
                localIntent.putExtras(finishBundle);

                sendBroadcast(localIntent);
                // System.out.println("Finished!!!");
            }
        }.start();

        return super.onStartCommand(intent, flags, startId);
    }

    @Override
    public void onSensorChanged(SensorEvent sensorEvent) {
        Sensor sensor = sensorEvent.sensor;

        if (sensor.getType() == Sensor.TYPE_LIGHT) {
            lightReading = sensorEvent.values[0];
        } else if (sensor.getType() == Sensor.TYPE_PROXIMITY) {
            proximityReading = sensorEvent.values[0];
        } else if (sensor.getType() == Sensor.TYPE_STEP_DETECTOR) {
            if (sensorEvent.values[0] > 0 && lightReading < 5.0
                && proximityReading < 1.0) {
                numOfSteps += 1;
            }
        } else if (sensor.getType() == Sensor.TYPE_ACCELEROMETER) {

            if (sensorEvent.values[2] > 9 && sensorEvent.values[2] < 11 && lightReading < 5.0
                    && proximityReading < 1.0) {
                // landed
                if (jumpStarted) {
                   // Log.d("onSensorChange", "landed z acceleration " + Float.toString(sensorEvent.values[2]));

                    numOfJumps += 1;
                    jumpStarted = false;
                }
            } else if (sensorEvent.values[2] < 1 && sensorEvent.values[2] > -1) {
                // free fall
                if (!jumpStarted) {
                    jumpStarted = true;
                }
            }
        }
    }

    @Override
    public void onAccuracyChanged(Sensor sensor, int i) {

    }
}
